package com.quartet.modules.service.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quartet.api.ApiResult;
import com.quartet.api.MapServerException;
import com.quartet.api.PageResult;
import com.quartet.api.ResultErrorEnum;
import com.quartet.modules.customer.entity.TCustomerInfo;
import com.quartet.modules.customer.service.TCustomerInfoService;
import com.quartet.modules.order.entity.TOrder;
import com.quartet.modules.order.service.TOrderService;
import com.quartet.modules.quartz.utils.HttpUtils;
import com.quartet.modules.service.dto.TServiceInfoAddRequestDto;
import com.quartet.modules.service.dto.TServiceInfoQueryRequestDto;
import com.quartet.modules.service.dto.TServiceInfoResponseDto;
import com.quartet.modules.service.dto.TServiceNameResponseDto;
import com.quartet.modules.service.entity.TServiceInfo;
import com.quartet.modules.service.service.TServiceInfoService;
import com.quartet.modules.stock.dto.TTerminalServiceMessageDto;
import com.quartet.modules.stock.entity.TTerminalStock;
import com.quartet.modules.stock.service.TTerminalStockService;
import com.quartet.modules.system.service.DictDetailServicePs;
import com.quartet.modules.terminal.entity.TTerminalInfo;
import com.quartet.modules.terminal.service.TTerminalInfoService;
import com.quartet.utils.BeanTool;
import com.quartet.utils.JsonTool;
import com.quartet.utils.constant.MapServerConstant;
import com.quartet.utils.enums.ServiceStatusEnum;
import com.quartet.utils.enums.ServiceTypeEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 服务信息表(TServiceInfo)表控制层
 *
 * @author makejava
 * @since 2021-05-24 17:51:09
 */
@RestController
@RequestMapping("tServiceInfo")
@Slf4j
@Api(tags = "业务：服务管理")
public class TServiceInfoController {
    /**
     * 服务对象
     */
    @Resource
    private TServiceInfoService tServiceInfoService;

    @Resource
    private TOrderService tOrderService;

    @Resource
    private DictDetailServicePs dictDetailServicePs;

    @Resource
    private TCustomerInfoService tCustomerInfoService;

    @Resource
    private TTerminalStockService tTerminalStockService;

    @Resource
    private TTerminalInfoService tTerminalInfoService;

    /**
     * 分页查询所有服务数据
     *
     * @param tServiceInfoQueryRequestDto 查询实体
     * @return 所有数据
     */
    @ApiOperation("分页查询所有服务数据")
    @PostMapping("/selectServiceByCondition")
    public ApiResult<PageResult<TServiceInfoResponseDto>> selectServiceByCondition(@RequestBody TServiceInfoQueryRequestDto tServiceInfoQueryRequestDto) {
        log.info("---------selectServiceByCondition begin, tServiceInfoQueryRequestDto is {}----------", tServiceInfoQueryRequestDto);
        IPage<TServiceInfo> page = new Page<>(tServiceInfoQueryRequestDto.getCurrent(), tServiceInfoQueryRequestDto.getLimit());
        QueryWrapper<TServiceInfo> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(tServiceInfoQueryRequestDto.getServiceName())) {
            queryWrapper.lambda().like(TServiceInfo::getServiceName, tServiceInfoQueryRequestDto.getServiceName());
        }
        if (StringUtils.isNotBlank(tServiceInfoQueryRequestDto.getServiceType())) {
            queryWrapper.lambda().eq(TServiceInfo::getServiceType, tServiceInfoQueryRequestDto.getServiceType());
        }
        if (!ObjectUtils.isEmpty(tServiceInfoQueryRequestDto.getServiceStatus())) {
            queryWrapper.lambda().eq(TServiceInfo::getStatus, tServiceInfoQueryRequestDto.getServiceStatus());
        }
        if (StringUtils.isNotBlank(tServiceInfoQueryRequestDto.getOrderName())) {
            QueryWrapper<TOrder> queryWrapper2 = new QueryWrapper();
            queryWrapper2.lambda().like(TOrder::getOrderName, tServiceInfoQueryRequestDto.getOrderName());
            List<String> orderCodeList = tOrderService.list(queryWrapper2).stream().map(tOrder -> tOrder.getOrderCode()).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(orderCodeList)) {
                queryWrapper.lambda().in(TServiceInfo::getOrderCode, orderCodeList);
            } else {
                PageResult<TServiceInfoResponseDto> pageResult = new PageResult();
                pageResult.setData(Collections.emptyList());
                pageResult.setTotal(0L);
                return ApiResult.ok(pageResult);
            }
        }
        IPage<TServiceInfo> dbResult = tServiceInfoService.page(page, queryWrapper);
        PageResult<TServiceInfoResponseDto> pageResult = new PageResult();
        List<TServiceInfoResponseDto> tServiceInfoResponseDtoList = dbResult.getRecords().stream().map(tServiceInfo -> {
            TServiceInfoResponseDto tServiceInfoResponseDto = BeanUtil.copyProperties(tServiceInfo, TServiceInfoResponseDto.class);
            if (!ObjectUtils.isEmpty(tServiceInfo.getAlarmType())) {
                List<String> alarmTypeList = JSON.parseArray(tServiceInfo.getAlarmType().toString(), String.class);
                tServiceInfoResponseDto.setAlarmType(alarmTypeList);
            }
            QueryWrapper<TOrder> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.lambda().eq(TOrder::getOrderCode, tServiceInfo.getOrderCode());
            tServiceInfoResponseDto.setServiceTypeLabel(dictDetailServicePs.getLabelByValueByCode(tServiceInfoResponseDto.getServiceType()));
            TOrder tOrder = tOrderService.getOne(queryWrapper1);
            if (ObjectUtils.isEmpty(tOrder)) {
                return tServiceInfoResponseDto;
            }
            tServiceInfoResponseDto.setOrderName(tOrder.getOrderName());

            QueryWrapper<TCustomerInfo> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.lambda().eq(TCustomerInfo::getCustomerCode, tOrder.getCustomerCode());
            TCustomerInfo tCustomerInfo = tCustomerInfoService.getOne(queryWrapper2);
            if (ObjectUtils.isEmpty(tCustomerInfo)) {
                return tServiceInfoResponseDto;
            }
            tServiceInfoResponseDto.setCustomerName(tCustomerInfo.getCustomerName());
            return tServiceInfoResponseDto;
        }).collect(Collectors.toList());
        pageResult.setTotal(dbResult.getTotal());
        pageResult.setData(tServiceInfoResponseDtoList);
        log.info("---------selectServiceByCondition end, data is {}----------", pageResult);
        return ApiResult.ok(pageResult);
    }

    /**
     * 通过主键查询单条服务数据
     *
     * @param id 主键
     * @return 单条数据
     */
    @ApiOperation("通过主键查询单条服务数据")
    @GetMapping("/selectServiceById")
    public ApiResult<TServiceInfoResponseDto> selectServiceById(@RequestParam("id") Integer id) {
        TServiceInfo tServiceInfo = tServiceInfoService.getById(id);
        TServiceInfoResponseDto tServiceInfoResponseDto = BeanUtil.copyProperties(tServiceInfo, TServiceInfoResponseDto.class);
        if (!ObjectUtils.isEmpty(tServiceInfo.getAlarmType())) {
            List<String> alarmTypeList = JSON.parseArray(tServiceInfo.getAlarmType().toString(), String.class);
            tServiceInfoResponseDto.setAlarmType(alarmTypeList);
        }
        tServiceInfoResponseDto.setServiceTypeLabel(dictDetailServicePs.getLabelByValueByCode(tServiceInfoResponseDto.getServiceType()));
        return ApiResult.ok(tServiceInfoResponseDto);
    }

    /**
     * 新增服务数据
     *
     * @param tServiceInfoAddRequestDto 实体对象
     * @return 新增结果
     */
    @ApiOperation("新增服务数据")
    @PostMapping("addService")
    @Transactional(rollbackFor = Exception.class)
    public ApiResult addService(@RequestBody TServiceInfoAddRequestDto tServiceInfoAddRequestDto) {
        synchronized (this){
            QueryWrapper<TServiceInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(TServiceInfo::getOrderCode, tServiceInfoAddRequestDto.getOrderCode())
                    .eq(TServiceInfo::getServiceType, tServiceInfoAddRequestDto.getServiceType());
            int count = tServiceInfoService.count(queryWrapper);
            if (count > 0) {
                throw new MapServerException(ResultErrorEnum.BMKPF001);
            }
            TServiceInfo tServiceInfo = BeanUtil.copyProperties(tServiceInfoAddRequestDto, TServiceInfo.class);
            if (!Objects.isNull(tServiceInfoAddRequestDto.getAlarmType())) {
                tServiceInfo.setAlarmType(JsonTool.beanToJson(tServiceInfoAddRequestDto.getAlarmType()));
            }
            this.tServiceInfoService.save(tServiceInfo);
            //给协议方发送终端权限信息
            sendAuthInfoWhenUpdateService(tServiceInfoAddRequestDto.getOrderCode());
//        tTerminalStockService.sendTTerminalServiceMessageDto();
            return ApiResult.ok();
        }
    }

    /**
     * 增加服务或者修改服务时推送权限数据
     *
     * @param orderCode
     */
    private void sendAuthInfoWhenUpdateService(String orderCode) {
        List<TTerminalStock> tTerminalStockList = tTerminalStockService.list(new QueryWrapper<TTerminalStock>().lambda().eq(TTerminalStock::getOrderCode, orderCode));
        if (CollectionUtils.isEmpty(tTerminalStockList)){
            return;
        }
        List<TServiceInfo> tServiceInfoList = tServiceInfoService.list(new QueryWrapper<TServiceInfo>().lambda()
                .eq(TServiceInfo::getOrderCode, orderCode)
                .eq(TServiceInfo::getStatus, ServiceStatusEnum.ENABLE.getValue())
                .in(TServiceInfo::getServiceType, MapServerConstant.SERVICE_TYPE_LIST));
        Map<String, List<String>> map = tServiceInfoList.stream().collect(Collectors.groupingBy(TServiceInfo::getOrderCode, Collectors.mapping(TServiceInfo::getServiceType, Collectors.toList())));
        List<String> serviceTypeList = map.get(orderCode);
        List<TTerminalServiceMessageDto> tTerminalServiceMessageDtoList = tTerminalStockList.stream().map(tTerminalStock -> {
            TTerminalServiceMessageDto tTerminalServiceMessageDto = new TTerminalServiceMessageDto();
            TTerminalInfo tTerminalInfo = tTerminalInfoService.getOne(new QueryWrapper<TTerminalInfo>().lambda().eq(TTerminalInfo::getTerminalCode, tTerminalStock.getTerminalCode()));
            tTerminalServiceMessageDto.setFlowCardNumber(tTerminalInfo.getFlowCardNumber());
            if (CollectionUtils.isEmpty(serviceTypeList)) {
                tTerminalServiceMessageDto.setAlarmAuth(false);
                tTerminalServiceMessageDto.setLocationAuth(false);
            } else {
                tTerminalServiceMessageDto.setLocationAuth(serviceTypeList.contains(MapServerConstant.LOCATION));
                tTerminalServiceMessageDto.setAlarmAuth(serviceTypeList.contains(MapServerConstant.ALARM));
            }
            return tTerminalServiceMessageDto;
        }).collect(Collectors.toList());
        log.info("新增、修改、停启用或者删除服务时推送的权限数据为：{}",tTerminalServiceMessageDtoList);
        HttpUtils.sendAuthInfo(tTerminalServiceMessageDtoList);
    }

    /**
     * 修改服务信息
     *
     * @param tServiceInfoAddRequestDto 实体对象
     * @return 修改结果
     */
    @ApiOperation("修改服务信息")
    @PutMapping("/updateService")
    @Transactional(rollbackFor = Exception.class)
    public ApiResult updateService(@RequestBody TServiceInfoAddRequestDto tServiceInfoAddRequestDto) {
        TServiceInfo tServiceInfo = BeanUtil.copyProperties(tServiceInfoAddRequestDto, TServiceInfo.class);
        if (!Objects.isNull(tServiceInfoAddRequestDto.getAlarmType())) {
            tServiceInfo.setAlarmType(JsonTool.beanToJson(tServiceInfoAddRequestDto.getAlarmType()));
        }

        TServiceInfo serviceInfo = tServiceInfoService.getById(tServiceInfoAddRequestDto.getId());
        //如果更换了订单 就要推送权限信息 否则不推送
        if (!serviceInfo.getOrderCode().equals(tServiceInfoAddRequestDto.getOrderCode())) {
            //1、推送之前订单的权限信息
            String orderCode = serviceInfo.getOrderCode();
            sendAuthInfoWhenUpdateService(orderCode);
            //2、修改服务信息
            this.tServiceInfoService.updateById(tServiceInfo);
            //3、推送新订单的权限信息
            sendAuthInfoWhenUpdateService(tServiceInfoAddRequestDto.getOrderCode());
        } else {
            this.tServiceInfoService.updateById(tServiceInfo);
        }
        //给协议方发送终端权限信息
//        tTerminalStockService.sendTTerminalServiceMessageDto();
        return ApiResult.ok();
    }

    /**
     * 删除服务信息
     *
     * @param id 主键
     * @return 删除结果
     */
    @ApiOperation("删除服务信息")
    @DeleteMapping("/deleteById")
    @Transactional(rollbackFor = Exception.class)
    public ApiResult deleteById(@RequestParam("id") Integer id) {
        TServiceInfo tServiceInfo = tServiceInfoService.getById(id);
        this.tServiceInfoService.removeById(id);
        //给协议方发送终端权限信息
        sendAuthInfoWhenUpdateService(tServiceInfo.getOrderCode());
//        tTerminalStockService.sendTTerminalServiceMessageDto();
        return ApiResult.ok();
    }

    /**
     * 启用禁用服务
     *
     * @param id 主键
     * @return 启用结果
     */
    @ApiOperation("启用禁用服务")
    @PostMapping("/updateStatusById")
    public ApiResult updateStatusById(@RequestParam("id") Integer id, @RequestParam("status") Integer status) {
        log.info("修改服务的状态，参数为：{}，{}",id,status);
        TServiceInfo tServiceInfo = tServiceInfoService.getById(id);
        UpdateWrapper<TServiceInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(TServiceInfo::getId, id).set(TServiceInfo::getStatus, status);
        tServiceInfoService.update(updateWrapper);
        //给协议方发送终端权限信息
        sendAuthInfoWhenUpdateService(tServiceInfo.getOrderCode());
//        tTerminalStockService.sendTTerminalServiceMessageDto();
        return ApiResult.ok();
    }

    /**
     * 查询地图服务配置
     *
     * @param id 主键
     * @return 启用结果
     */
    @ApiOperation("查询地图服务配置")
    @GetMapping("/queryMapJson")
    public ApiResult<String> queryMapJson(@RequestParam("id") Integer id, @RequestParam(value = "customerCode", required = false) String customerCode) {
        if (StringUtils.isNotBlank(customerCode)) {
            QueryWrapper<TOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(TOrder::getCustomerCode, customerCode);
            List<TOrder> tOrderList = tOrderService.list(queryWrapper);
            if(CollectionUtil.isEmpty(tOrderList)){
                return  ApiResult.ok();
            }
            List<String> orderCodeList = tOrderList.stream().map(tOrder -> tOrder.getOrderCode()).collect(Collectors.toList());
            QueryWrapper<TServiceInfo> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.lambda().in(TServiceInfo::getOrderCode, orderCodeList).eq(TServiceInfo::getId, id);
            List<TServiceInfo> tServiceInfoList = tServiceInfoService.list(queryWrapper1);
            if (CollectionUtils.isEmpty(tServiceInfoList)) {
                return ApiResult.ok();
            } else {
                return ApiResult.ok(tServiceInfoList.get(0).getMapJson());
            }
        } else {
            TServiceInfo tServiceInfo = tServiceInfoService.getById(id);
            if (Objects.isNull(tServiceInfo)){
                return ApiResult.ok();
            }
            return ApiResult.ok(tServiceInfo.getMapJson());
        }
    }

    /**
     * 根据客户编码查询地图服务id和名称
     *
     * @param customerCode 主键
     * @return 启用结果
     */
    @ApiOperation("根据客户编码查询地图服务id和名称")
    @GetMapping("/queryMapNameListByCustomerCode")
    public ApiResult<List<TServiceNameResponseDto>> queryMapNameListByCustomerCode(@RequestParam("customerCode") String customerCode) {
        QueryWrapper<TOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TOrder::getCustomerCode, customerCode);
        List<TOrder> tOrderList = tOrderService.list(queryWrapper);
        List<String> orderCodeList = tOrderList.stream().map(tOrder -> tOrder.getOrderCode()).collect(Collectors.toList());

        QueryWrapper<TServiceInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.lambda().in(TServiceInfo::getOrderCode, orderCodeList).eq(TServiceInfo::getServiceType, ServiceTypeEnum.MAP.getValue());
        List<TServiceInfo> tServiceInfoList = tServiceInfoService.list(queryWrapper1);
        List<TServiceNameResponseDto> tServiceNameResponseDtoList = BeanTool.copyObjListProperties(tServiceInfoList, TServiceNameResponseDto.class);
        return ApiResult.ok(tServiceNameResponseDtoList);
    }
}